#include "Player.h"
#include "config.h"
#include <cmath>

Player::Player(b2World * w)
: GameEntity(w)
, state(ROUND)
, propCount(0)
, canJump(false)
, level(0)
, speed(10)
, pPlayerEventListener(NULL)
{
}

Player::~Player()
{
}

Player * Player::create(b2World * pWorld)
{
  Player * pPlayer = new Player(pWorld);
  if (pPlayer && pPlayer->init())
  {
    pPlayer->autorelease();
    return pPlayer;
  }
  else
  {
    CC_SAFE_DELETE(pPlayer);
    return NULL;
  }
}

EntityType Player::getEntityType()
{
  return PLAYER;
}

bool Player::init()
{

  createBody();
  setPTMRatio(PTM_RATIO);
  initWithSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("player_round.png"));
  return true;
}

void Player::action(PlayerAction action)
{
  switch(action)
  {
    case JUMP:
        if (canJump)
        {
          canJump = false;
          m_pB2Body->SetLinearVelocity(b2Vec2(m_pB2Body->GetLinearVelocity().x, 8));
        }
      break;
    case ROUND:
      for (b2Fixture * f = m_pB2Body->GetFixtureList(); f; f->GetNext())
      {
        if ((int)(f->GetUserData()) == 2)
        {
          m_pB2Body->DestroyFixture(f);
          break;
        }
      }
      break;
    case RUN:
      {
        b2PolygonShape dynamicBox;
        dynamicBox.SetAsBox(PLAYER_WIDTH/2, PLAYER_HEIGHT/4, b2Vec2(0, (PLAYER_HEIGHT/2)), 0);//These are mid points for our 1m box

        b2FixtureDef fixtureDef;
        fixtureDef.shape = &dynamicBox;    
        fixtureDef.density = 0.0f;
        fixtureDef.friction = 0.0f;
        fixtureDef.restitution = 0.0f;
        fixtureDef.userData = (void *)2;
        m_pB2Body->CreateFixture(&fixtureDef);
      }
      break;
    case NORMAL_SPEED:
      {
        m_pB2Body->SetLinearVelocity(b2Vec2(this->getSpeed(), m_pB2Body->GetLinearVelocity().y));
      }
      break;
    case DEAD:
      {
        m_pB2Body->SetLinearVelocity(b2Vec2(0, 0));
        if (pPlayerEventListener)
        {
          pPlayerEventListener->onPlayerDead();
        }
      }
    default:
      break;
  }
  state = action;
}

void Player::getProp(PropType type)
{
  propCount++;
  pPlayerEventListener->setPropCount(propCount);
}

void Player::createBody()
{
  b2BodyDef bodyDef;
  bodyDef.type = b2_dynamicBody;
  bodyDef.linearDamping = 0.0f;
  bodyDef.position.Set(PLAYER_WIDTH/2 + PLAYER_POS_OFFSET_X, PLAYER_POS_OFFSET_Y + PLAYER_HEIGHT/2);

  m_pB2Body = pWorld->CreateBody(&bodyDef);
  m_pB2Body->SetLinearVelocity(b2Vec2(this->getSpeed(), 0));

  b2FixtureDef fixtureDef;
  b2CircleShape circle;
  circle.m_radius = PLAYER_WIDTH/2;

  fixtureDef.shape = &circle;    
  fixtureDef.density = 1.0f;
  fixtureDef.friction = 0.0f;
  fixtureDef.restitution = 0.0f;
  fixtureDef.userData = (void *)1;
  m_pB2Body->CreateFixture(&fixtureDef);
  m_pB2Body->SetFixedRotation(true);

  b2PolygonShape dynamicBox;
  dynamicBox.SetAsBox(PLAYER_WIDTH/2, PLAYER_HEIGHT/4, b2Vec2(0, (PLAYER_HEIGHT/2)), 0);//These are mid points for our 1m box

  fixtureDef.shape = &dynamicBox;    
  fixtureDef.density = 0.0f;
  fixtureDef.friction = 0.0f;
  fixtureDef.restitution = 0.0f;
  fixtureDef.userData = (void *)2;
  m_pB2Body->CreateFixture(&fixtureDef);

  m_pB2Body->SetUserData((GameEntity *)this);
}

void Player::setPlayerEventListener(PlayerEventListener * pPlayerEventListener)
{
  this->pPlayerEventListener = pPlayerEventListener;
}

void Player::restart()
{
  setLevel(0);
  m_pB2Body->SetTransform(b2Vec2(PLAYER_WIDTH/2 + PLAYER_POS_OFFSET_X, PLAYER_POS_OFFSET_Y + PLAYER_HEIGHT/2), 0);
  m_pB2Body->SetLinearVelocity(b2Vec2(10, 0));
  propCount = 0;
}

void Player::setCanJump()
{
  canJump = true;
}

void Player::setLevel(int level)
{
  this->level = level;
  this->speed = 10 * pow(1.02f, level);
}

float Player::getSpeed()
{
  return this->speed;
}
